In this notebook, we will explore our preprocessed dataset. We will analyze the data for outliers, correlated features, and merits in features against the selected features the model outputs. We will use different feature selection methods such as PCA, Forward/Backward selection, and Decision Trees; and will determine which features we can exclude based on the results and error rate. We want to train our models only on the features most important to determining the popularity of the song per genre (with the exception of Decision Tree since it performs its own feature selection).
We use kMeans to explore how well kMeans could predict a song's popularity based on its features and perhaps even if it can cluster songs into genres based on the track's features.
This data has been preprocessed and does not contain null values.
import pandas as pd
import numpy as np
raw_data = pd.read_csv('./data/rawData_final.csv')
raw_data.head(3)
| year | genre | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | ... | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2016 | jazz | 0 | 0 | 0.6770 | 0.566 | 0.468 | 0.094330 | 0.000025 | 0.718 | ... | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
| 1 | 2017 | latin | 0 | 0 | 0.0317 | 0.709 | 0.744 | 0.166493 | 0.000000 | 0.314 | ... | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 |
| 2 | 2017 | latin | 0 | 0 | 0.3920 | 0.787 | 0.732 | 0.143168 | 0.000003 | 0.897 | ... | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
3 rows × 34 columns
print(raw_data.shape)
raw_data.describe(include='all').T
(23127, 34)
| count | unique | top | freq | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 23127 | NaN | NaN | NaN | 2011.24 | 5.42064 | 2002 | 2007 | 2011 | 2016 | 2020 |
| genre | 23127 | 5 | r&b | 5233 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | 23127 | NaN | NaN | NaN | 0.244476 | 0.429785 | 0 | 0 | 0 | 0 | 1 |
| chartrank | 23127 | NaN | NaN | NaN | 10.1429 | 22.372 | 0 | 0 | 0 | 0 | 100 |
| acousticness | 23127 | NaN | NaN | NaN | 0.292056 | 0.283272 | 2.05e-06 | 0.0513 | 0.193 | 0.4785 | 0.996 |
| danceability | 23127 | NaN | NaN | NaN | 0.622599 | 0.143972 | 0.0917 | 0.526 | 0.631 | 0.729 | 0.976 |
| energy | 23127 | NaN | NaN | NaN | 0.623486 | 0.206216 | 0.00154 | 0.493 | 0.652 | 0.783 | 0.997 |
| duration_ms | 23127 | NaN | NaN | NaN | 0.130604 | 0.0432525 | 0 | 0.107969 | 0.125852 | 0.14664 | 1 |
| instrumentalness | 23127 | NaN | NaN | NaN | 0.0895416 | 0.242499 | 0 | 0 | 2.14e-06 | 0.0007815 | 0.988 |
| valence | 23127 | NaN | NaN | NaN | 0.532651 | 0.238052 | 0.0266 | 0.344 | 0.534 | 0.725 | 0.983 |
| tempo | 23127 | NaN | NaN | NaN | 0.462231 | 0.166387 | 0 | 0.32434 | 0.454912 | 0.566718 | 1 |
| liveness | 23127 | NaN | NaN | NaN | 0.190227 | 0.164199 | 0.0136 | 0.0948 | 0.124 | 0.232 | 0.997 |
| loudness | 23127 | NaN | NaN | NaN | 0.824212 | 0.0886051 | 0 | 0.792247 | 0.844263 | 0.880523 | 1 |
| speechiness | 23127 | NaN | NaN | NaN | 0.0827893 | 0.0876328 | 0.0225 | 0.0339 | 0.0459 | 0.0869 | 0.922 |
| key_0 | 23127 | NaN | NaN | NaN | 0.118476 | 0.323178 | 0 | 0 | 0 | 0 | 1 |
| key_1 | 23127 | NaN | NaN | NaN | 0.105072 | 0.306653 | 0 | 0 | 0 | 0 | 1 |
| key_2 | 23127 | NaN | NaN | NaN | 0.0928785 | 0.290268 | 0 | 0 | 0 | 0 | 1 |
| key_3 | 23127 | NaN | NaN | NaN | 0.0319972 | 0.175996 | 0 | 0 | 0 | 0 | 1 |
| key_4 | 23127 | NaN | NaN | NaN | 0.070221 | 0.255525 | 0 | 0 | 0 | 0 | 1 |
| key_5 | 23127 | NaN | NaN | NaN | 0.0914948 | 0.288318 | 0 | 0 | 0 | 0 | 1 |
| key_6 | 23127 | NaN | NaN | NaN | 0.0685779 | 0.25274 | 0 | 0 | 0 | 0 | 1 |
| key_7 | 23127 | NaN | NaN | NaN | 0.113417 | 0.317109 | 0 | 0 | 0 | 0 | 1 |
| key_8 | 23127 | NaN | NaN | NaN | 0.0707831 | 0.256468 | 0 | 0 | 0 | 0 | 1 |
| key_9 | 23127 | NaN | NaN | NaN | 0.0905868 | 0.287027 | 0 | 0 | 0 | 0 | 1 |
| key_10 | 23127 | NaN | NaN | NaN | 0.0687941 | 0.253109 | 0 | 0 | 0 | 0 | 1 |
| key_11 | 23127 | NaN | NaN | NaN | 0.0777014 | 0.267707 | 0 | 0 | 0 | 0 | 1 |
| explicit_0 | 23127 | NaN | NaN | NaN | 0.850348 | 0.356738 | 0 | 1 | 1 | 1 | 1 |
| explicit_1 | 23127 | NaN | NaN | NaN | 0.149652 | 0.356738 | 0 | 0 | 0 | 0 | 1 |
| mode_0 | 23127 | NaN | NaN | NaN | 0.344922 | 0.475353 | 0 | 0 | 0 | 1 | 1 |
| mode_1 | 23127 | NaN | NaN | NaN | 0.655078 | 0.475353 | 0 | 0 | 1 | 1 | 1 |
| time_signature_1 | 23127 | NaN | NaN | NaN | 0.00583733 | 0.0761808 | 0 | 0 | 0 | 0 | 1 |
| time_signature_3 | 23127 | NaN | NaN | NaN | 0.0667186 | 0.249539 | 0 | 0 | 0 | 0 | 1 |
| time_signature_4 | 23127 | NaN | NaN | NaN | 0.916591 | 0.276505 | 0 | 1 | 1 | 1 | 1 |
| time_signature_5 | 23127 | NaN | NaN | NaN | 0.0108531 | 0.103614 | 0 | 0 | 0 | 0 | 1 |
We have a total of 17,473 track objects, 5,654 of which are our 'popular' (aka target) tracks. The total number of tracks per genre is distributed within a few standard deviations of one another. The average amount of tracks per genre is 4,625. The pop genre has the lowest count with 4,158 tracks. The r&b genre has the highest count at 5,233 tracks.
print("Unpopular & popular counts:\n", raw_data.popular.value_counts())
Unpopular & popular counts: 0 17473 1 5654 Name: popular, dtype: int64
print("Tracks per genre count:\n", raw_data.genre.value_counts())
print("\nMean distribution of tracks per genre: ", (raw_data.genre.value_counts().sum())/(raw_data.genre.value_counts().shape[0]))
Tracks per genre count: r&b 5233 country 4739 latin 4709 jazz 4288 pop 4158 Name: genre, dtype: int64 Mean distribution of tracks per genre: 4625.4
# Standard deviation of tracks per genre
raw_data.genre.value_counts().std()
424.66845891824835
raw_data.boxplot(column=['acousticness', 'danceability', 'energy', 'duration_ms'])
<AxesSubplot:>
raw_data.boxplot(column=['instrumentalness', 'valence', 'tempo'])
<AxesSubplot:>
raw_data.boxplot(column=['liveness', 'loudness', 'speechiness'])
<AxesSubplot:>
raw_data.boxplot(column=['key_0', 'key_1', 'key_2', 'key_3', 'key_4', 'key_5'])
<AxesSubplot:>
raw_data.boxplot(column=['key_6', 'key_7', 'key_8', 'key_9', 'key_10', 'key_11', ])
<AxesSubplot:>
raw_data.boxplot(column=['explicit_0', 'explicit_1', 'mode_0', 'mode_1'])
<AxesSubplot:>
raw_data.boxplot(column=['time_signature_1', 'time_signature_3', 'time_signature_4','time_signature_5'])
<AxesSubplot:>
pd.options.display.max_columns = 40
raw_data.corr()
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.000000 | 0.138451 | 0.130752 | -0.002452 | 0.046851 | -0.021573 | -0.167721 | 0.067053 | -0.103803 | 0.021754 | -0.023592 | 0.002073 | 0.049199 | -0.002263 | 0.015966 | -0.032831 | -0.004625 | -0.008777 | 0.001609 | 0.026043 | -0.015778 | 0.010659 | -0.016223 | 0.015503 | 0.016352 | -0.160330 | 0.160330 | 0.038952 | -0.038952 | 0.022530 | 0.021820 | -0.024109 | -0.004779 |
| popular | 0.138451 | 1.000000 | 0.797029 | -0.169428 | 0.151191 | 0.166754 | -0.052411 | -0.061045 | 0.114409 | 0.032547 | -0.065085 | 0.220876 | 0.053378 | -0.015835 | 0.019332 | -0.001087 | -0.009668 | -0.011430 | 0.001985 | 0.002094 | -0.016264 | 0.021887 | -0.015486 | 0.010748 | 0.016039 | -0.120955 | 0.120955 | -0.004908 | 0.004908 | -0.009251 | -0.021057 | 0.020957 | 0.001589 |
| chartrank | 0.130752 | 0.797029 | 1.000000 | -0.144451 | 0.115322 | 0.136503 | -0.058011 | -0.099075 | 0.082280 | 0.033867 | -0.040205 | 0.191342 | 0.082973 | -0.013688 | 0.018005 | -0.002551 | -0.005895 | -0.003360 | 0.000406 | 0.007925 | -0.014646 | 0.013317 | -0.010427 | 0.004846 | 0.009019 | -0.142394 | 0.142394 | -0.010256 | 0.010256 | -0.000972 | 0.001475 | -0.000855 | -0.000557 |
| acousticness | -0.002452 | -0.169428 | -0.144451 | 1.000000 | -0.209523 | -0.660217 | 0.020545 | 0.226459 | -0.218070 | -0.115901 | -0.070233 | -0.568515 | -0.126149 | 0.039998 | -0.073837 | 0.001789 | 0.061509 | 0.010325 | 0.039661 | -0.034303 | 0.015086 | -0.011588 | 0.008964 | 0.019415 | -0.061004 | 0.139627 | -0.139627 | -0.046240 | 0.046240 | 0.030794 | 0.191595 | -0.187576 | 0.016498 |
| danceability | 0.046851 | 0.151191 | 0.115322 | -0.209523 | 1.000000 | 0.166004 | -0.103111 | -0.077973 | 0.433544 | -0.148001 | -0.133937 | 0.213652 | 0.169115 | -0.026090 | 0.072236 | -0.027590 | -0.047143 | -0.043062 | -0.007849 | 0.017933 | -0.022289 | 0.015157 | -0.009861 | 0.032229 | 0.034267 | -0.211484 | 0.211484 | 0.127450 | -0.127450 | -0.045260 | -0.183928 | 0.208624 | -0.080495 |
| energy | -0.021573 | 0.166754 | 0.136503 | -0.660217 | 0.166004 | 1.000000 | -0.066631 | -0.216517 | 0.456319 | 0.158591 | 0.135999 | 0.758895 | 0.114181 | -0.042096 | 0.031699 | 0.012795 | -0.042484 | 0.003595 | -0.026451 | 0.018111 | -0.012146 | 0.003228 | 0.001124 | -0.007765 | 0.053954 | -0.025200 | 0.025200 | 0.033573 | -0.033573 | -0.035892 | -0.204070 | 0.204081 | -0.026750 |
| duration_ms | -0.167721 | -0.052411 | -0.058011 | 0.020545 | -0.103111 | -0.066631 | 1.000000 | 0.129611 | -0.166101 | -0.031343 | 0.066335 | -0.097962 | -0.046720 | 0.008103 | 0.007667 | 0.009259 | 0.012673 | -0.020157 | 0.034351 | -0.018302 | -0.005728 | -0.005835 | -0.011605 | -0.014414 | 0.001032 | 0.003488 | -0.003488 | 0.057073 | -0.057073 | -0.031908 | -0.026305 | 0.033703 | -0.003129 |
| instrumentalness | 0.067053 | -0.061045 | -0.099075 | 0.226459 | -0.077973 | -0.216517 | 0.129611 | 1.000000 | -0.084400 | -0.092717 | -0.043328 | -0.457803 | -0.121866 | 0.010065 | -0.023444 | -0.000572 | 0.016227 | -0.013213 | 0.046110 | -0.021020 | 0.009452 | -0.006836 | -0.013367 | 0.018726 | -0.020568 | 0.143067 | -0.143067 | 0.100709 | -0.100709 | 0.019908 | 0.036926 | -0.039173 | 0.000969 |
| valence | -0.103803 | 0.114409 | 0.082280 | -0.218070 | 0.433544 | 0.456319 | -0.166101 | -0.084400 | 1.000000 | 0.064667 | -0.004543 | 0.321009 | 0.075949 | -0.015091 | -0.004774 | -0.009778 | -0.016717 | -0.014916 | 0.012240 | 0.000384 | 0.005456 | -0.001464 | 0.006941 | 0.017789 | 0.016648 | 0.075448 | -0.075448 | 0.037845 | -0.037845 | -0.016496 | -0.100361 | 0.106037 | -0.029137 |
| tempo | 0.021754 | 0.032547 | 0.033867 | -0.115901 | -0.148001 | 0.158591 | -0.031343 | -0.092717 | 0.064667 | 1.000000 | 0.024525 | 0.149094 | 0.060678 | 0.007490 | -0.001627 | 0.010594 | 0.002791 | 0.023215 | -0.028198 | -0.005401 | 0.007594 | 0.014310 | -0.001872 | -0.031658 | 0.002043 | -0.016518 | 0.016518 | -0.049382 | 0.049382 | -0.025230 | 0.066462 | -0.046767 | -0.016710 |
| liveness | -0.023592 | -0.065085 | -0.040205 | -0.070233 | -0.133937 | 0.135999 | 0.066335 | -0.043328 | -0.004543 | 0.024525 | 1.000000 | 0.041753 | 0.077761 | 0.010725 | -0.022078 | 0.010823 | -0.008454 | 0.023308 | -0.003799 | -0.014982 | 0.015886 | -0.029941 | 0.005632 | -0.008451 | 0.013970 | -0.002618 | 0.002618 | -0.005156 | 0.005156 | 0.008300 | -0.007560 | 0.000520 | 0.010718 |
| loudness | 0.002073 | 0.220876 | 0.191342 | -0.568515 | 0.213652 | 0.758895 | -0.097962 | -0.457803 | 0.321009 | 0.149094 | 0.041753 | 1.000000 | 0.078700 | -0.036552 | 0.043918 | 0.001682 | -0.032414 | -0.006871 | -0.035604 | 0.026473 | -0.015711 | 0.019609 | -0.005361 | -0.003637 | 0.042227 | -0.098924 | 0.098924 | -0.005388 | 0.005388 | -0.044377 | -0.144820 | 0.155773 | -0.034292 |
| speechiness | 0.049199 | 0.053378 | 0.082973 | -0.126149 | 0.169115 | 0.114181 | -0.046720 | -0.121866 | 0.075949 | 0.060678 | 0.077761 | 0.078700 | 1.000000 | -0.042524 | 0.091425 | -0.044085 | -0.029621 | -0.036508 | -0.025755 | 0.046862 | -0.030514 | 0.027915 | -0.018951 | 0.018707 | 0.044259 | -0.388479 | 0.388479 | 0.129705 | -0.129705 | 0.044604 | -0.040067 | -0.017007 | 0.109086 |
| key_0 | -0.002263 | -0.015835 | -0.013688 | 0.039998 | -0.026090 | -0.042096 | 0.008103 | 0.010065 | -0.015091 | 0.007490 | 0.010725 | -0.036552 | -0.042524 | 1.000000 | -0.125617 | -0.117307 | -0.066653 | -0.100749 | -0.116341 | -0.099476 | -0.131123 | -0.101182 | -0.115705 | -0.099644 | -0.106409 | 0.019896 | -0.019896 | -0.093474 | 0.093474 | -0.001746 | 0.020478 | -0.013771 | -0.011283 |
| key_1 | 0.015966 | 0.019332 | 0.018005 | -0.073837 | 0.072236 | 0.031699 | 0.007667 | -0.023444 | -0.004774 | -0.001627 | -0.022078 | 0.043918 | 0.091425 | -0.125617 | 1.000000 | -0.109641 | -0.062297 | -0.094166 | -0.108739 | -0.092975 | -0.122555 | -0.094570 | -0.108144 | -0.093133 | -0.099455 | -0.092632 | 0.092632 | -0.034161 | 0.034161 | -0.009597 | -0.023805 | 0.020748 | 0.009019 |
| key_2 | -0.032831 | -0.001087 | -0.002551 | 0.001789 | -0.027590 | 0.012795 | 0.009259 | -0.000572 | -0.009778 | 0.010594 | 0.010823 | 0.001682 | -0.044085 | -0.117307 | -0.109641 | 1.000000 | -0.058176 | -0.087936 | -0.101545 | -0.086825 | -0.114447 | -0.088314 | -0.100990 | -0.086972 | -0.092876 | 0.032761 | -0.032761 | -0.104324 | 0.104324 | 0.002858 | 0.004590 | -0.004223 | -0.001887 |
| key_3 | -0.004625 | -0.009668 | -0.005895 | 0.061509 | -0.047143 | -0.042484 | 0.012673 | 0.016227 | -0.016717 | 0.002791 | -0.008454 | -0.032414 | -0.029621 | -0.066653 | -0.062297 | -0.058176 | 1.000000 | -0.049964 | -0.057697 | -0.049333 | -0.065028 | -0.050179 | -0.057381 | -0.049416 | -0.052771 | 0.010842 | -0.010842 | 0.008662 | -0.008662 | 0.008645 | 0.027203 | -0.024238 | -0.007188 |
| key_4 | -0.008777 | -0.011430 | -0.003360 | 0.010325 | -0.043062 | 0.003595 | -0.020157 | -0.013213 | -0.014916 | 0.023215 | 0.023308 | -0.006871 | -0.036508 | -0.100749 | -0.094166 | -0.087936 | -0.049964 | 1.000000 | -0.087212 | -0.074570 | -0.098293 | -0.075849 | -0.086735 | -0.074696 | -0.079767 | 0.033222 | -0.033222 | 0.062958 | -0.062958 | -0.001066 | 0.008578 | -0.004617 | -0.007554 |
| key_5 | 0.001609 | 0.001985 | 0.000406 | 0.039661 | -0.007849 | -0.026451 | 0.034351 | 0.046110 | 0.012240 | -0.028198 | -0.003799 | -0.035604 | -0.025755 | -0.116341 | -0.108739 | -0.101545 | -0.057697 | -0.087212 | 1.000000 | -0.086110 | -0.113505 | -0.087587 | -0.100158 | -0.086256 | -0.092111 | 0.034333 | -0.034333 | 0.091228 | -0.091228 | 0.001276 | -0.000707 | -0.003529 | 0.010183 |
| key_6 | 0.026043 | 0.002094 | 0.007925 | -0.034303 | 0.017933 | 0.018111 | -0.018302 | -0.021020 | 0.000384 | -0.005401 | -0.014982 | 0.026473 | 0.046862 | -0.099476 | -0.092975 | -0.086825 | -0.049333 | -0.074570 | -0.086110 | 1.000000 | -0.097051 | -0.074890 | -0.085639 | -0.073752 | -0.078758 | -0.022854 | 0.022854 | 0.053972 | -0.053972 | 0.026371 | -0.011529 | -0.001679 | 0.012858 |
| key_7 | -0.015778 | -0.016264 | -0.014646 | 0.015086 | -0.022289 | -0.012146 | -0.005728 | 0.009452 | 0.005456 | 0.007594 | 0.015886 | -0.015711 | -0.030514 | -0.131123 | -0.122555 | -0.114447 | -0.065028 | -0.098293 | -0.113505 | -0.097051 | 1.000000 | -0.098716 | -0.112884 | -0.097215 | -0.103815 | 0.031932 | -0.031932 | -0.082826 | 0.082826 | -0.004137 | 0.011474 | -0.005532 | -0.009828 |
| key_8 | 0.010659 | 0.021887 | 0.013317 | -0.011588 | 0.015157 | 0.003228 | -0.005835 | -0.006836 | -0.001464 | 0.014310 | -0.029941 | 0.019609 | 0.027915 | -0.101182 | -0.094570 | -0.088314 | -0.050179 | -0.075849 | -0.087587 | -0.074890 | -0.098716 | 1.000000 | -0.087108 | -0.075017 | -0.080110 | -0.030730 | 0.030730 | -0.061233 | 0.061233 | -0.003443 | -0.006228 | 0.005208 | 0.003634 |
| key_9 | -0.016223 | -0.015486 | -0.010427 | 0.008964 | -0.009861 | 0.001124 | -0.011605 | -0.013367 | 0.006941 | -0.001872 | 0.005632 | -0.005361 | -0.018951 | -0.115705 | -0.108144 | -0.100990 | -0.057381 | -0.086735 | -0.100158 | -0.085639 | -0.112884 | -0.087108 | 1.000000 | -0.085784 | -0.091607 | 0.020913 | -0.020913 | 0.014385 | -0.014385 | -0.004408 | -0.002279 | 0.003128 | 0.000382 |
| key_10 | 0.015503 | 0.010748 | 0.004846 | 0.019415 | 0.032229 | -0.007765 | -0.014414 | 0.018726 | 0.017789 | -0.031658 | -0.008451 | -0.003637 | 0.018707 | -0.099644 | -0.093133 | -0.086972 | -0.049416 | -0.074696 | -0.086256 | -0.073752 | -0.097215 | -0.075017 | -0.085784 | 1.000000 | -0.078892 | -0.006658 | 0.006658 | 0.079150 | -0.079150 | 0.003841 | 0.005375 | -0.006362 | 0.001208 |
| key_11 | 0.016352 | 0.016039 | 0.009019 | -0.061004 | 0.034267 | 0.053954 | 0.001032 | -0.020568 | 0.016648 | 0.002043 | 0.013970 | 0.042227 | 0.044259 | -0.106409 | -0.099455 | -0.092876 | -0.052771 | -0.079767 | -0.092111 | -0.078758 | -0.103815 | -0.080110 | -0.091607 | -0.078892 | 1.000000 | -0.032182 | 0.032182 | 0.116611 | -0.116611 | -0.011640 | -0.027117 | 0.027389 | 0.000775 |
| explicit_0 | -0.160330 | -0.120955 | -0.142394 | 0.139627 | -0.211484 | -0.025200 | 0.003488 | 0.143067 | 0.075448 | -0.016518 | -0.002618 | -0.098924 | -0.388479 | 0.019896 | -0.092632 | 0.032761 | 0.010842 | 0.033222 | 0.034333 | -0.022854 | 0.031932 | -0.030730 | 0.020913 | -0.006658 | -0.032182 | 1.000000 | -1.000000 | -0.096446 | 0.096446 | -0.001268 | 0.059705 | -0.037121 | -0.043796 |
| explicit_1 | 0.160330 | 0.120955 | 0.142394 | -0.139627 | 0.211484 | 0.025200 | -0.003488 | -0.143067 | -0.075448 | 0.016518 | 0.002618 | 0.098924 | 0.388479 | -0.019896 | 0.092632 | -0.032761 | -0.010842 | -0.033222 | -0.034333 | 0.022854 | -0.031932 | 0.030730 | -0.020913 | 0.006658 | 0.032182 | -1.000000 | 1.000000 | 0.096446 | -0.096446 | 0.001268 | -0.059705 | 0.037121 | 0.043796 |
| mode_0 | 0.038952 | -0.004908 | -0.010256 | -0.046240 | 0.127450 | 0.033573 | 0.057073 | 0.100709 | 0.037845 | -0.049382 | -0.005156 | -0.005388 | 0.129705 | -0.093474 | -0.034161 | -0.104324 | 0.008662 | 0.062958 | 0.091228 | 0.053972 | -0.082826 | -0.061233 | 0.014385 | 0.079150 | 0.116611 | -0.096446 | 0.096446 | 1.000000 | -1.000000 | 0.002908 | -0.052572 | 0.039266 | 0.019688 |
| mode_1 | -0.038952 | 0.004908 | 0.010256 | 0.046240 | -0.127450 | -0.033573 | -0.057073 | -0.100709 | -0.037845 | 0.049382 | 0.005156 | 0.005388 | -0.129705 | 0.093474 | 0.034161 | 0.104324 | -0.008662 | -0.062958 | -0.091228 | -0.053972 | 0.082826 | 0.061233 | -0.014385 | -0.079150 | -0.116611 | 0.096446 | -0.096446 | -1.000000 | 1.000000 | -0.002908 | 0.052572 | -0.039266 | -0.019688 |
| time_signature_1 | 0.022530 | -0.009251 | -0.000972 | 0.030794 | -0.045260 | -0.035892 | -0.031908 | 0.019908 | -0.016496 | -0.025230 | 0.008300 | -0.044377 | 0.044604 | -0.001746 | -0.009597 | 0.002858 | 0.008645 | -0.001066 | 0.001276 | 0.026371 | -0.004137 | -0.003443 | -0.004408 | 0.003841 | -0.011640 | -0.001268 | 0.001268 | 0.002908 | -0.002908 | 1.000000 | -0.020488 | -0.254015 | -0.008026 |
| time_signature_3 | 0.021820 | -0.021057 | 0.001475 | 0.191595 | -0.183928 | -0.204070 | -0.026305 | 0.036926 | -0.100361 | 0.066462 | -0.007560 | -0.144820 | -0.040067 | 0.020478 | -0.023805 | 0.004590 | 0.027203 | 0.008578 | -0.000707 | -0.011529 | 0.011474 | -0.006228 | -0.002279 | 0.005375 | -0.027117 | 0.059705 | -0.059705 | -0.052572 | 0.052572 | -0.020488 | 1.000000 | -0.886336 | -0.028007 |
| time_signature_4 | -0.024109 | 0.020957 | -0.000855 | -0.187576 | 0.208624 | 0.204081 | 0.033703 | -0.039173 | 0.106037 | -0.046767 | 0.000520 | 0.155773 | -0.017007 | -0.013771 | 0.020748 | -0.004223 | -0.024238 | -0.004617 | -0.003529 | -0.001679 | -0.005532 | 0.005208 | 0.003128 | -0.006362 | 0.027389 | -0.037121 | 0.037121 | 0.039266 | -0.039266 | -0.254015 | -0.886336 | 1.000000 | -0.347239 |
| time_signature_5 | -0.004779 | 0.001589 | -0.000557 | 0.016498 | -0.080495 | -0.026750 | -0.003129 | 0.000969 | -0.029137 | -0.016710 | 0.010718 | -0.034292 | 0.109086 | -0.011283 | 0.009019 | -0.001887 | -0.007188 | -0.007554 | 0.010183 | 0.012858 | -0.009828 | 0.003634 | 0.000382 | 0.001208 | 0.000775 | -0.043796 | 0.043796 | 0.019688 | -0.019688 | -0.008026 | -0.028007 | -0.347239 | 1.000000 |
# Find significant correlations
data_corr_df = pd.DataFrame(raw_data.corr(), copy=True)
data_corr_df.where(data_corr_df > 0.5)
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.797029 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.797029 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | 0.758895 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | NaN | NaN | 0.758895 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
We didn't find many features that are significantly correlated to "popularity" other than "chartrank", but that "chartrank" feature is expected to be correlated and therefore not insightful in this case. The only significant correlations to note are "energy" and "loudness" within all the data.
Let's see if we can find more correlations when we separate the data by genre.
data_per_genre = raw_data.groupby('genre')
for genre in raw_data.genre.unique():
print("Genre ", genre)
abs_corr = np.abs(data_per_genre.get_group(genre).corr())
display(abs_corr.where(abs_corr > 0.5))
print()
Genre jazz
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.836895 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.836895 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.000000 | NaN | 0.754809 | NaN | NaN | NaN | NaN | NaN | 0.632743 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | 0.579829 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | 0.754809 | NaN | 1.000000 | NaN | NaN | 0.583129 | NaN | NaN | 0.808687 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | 0.579829 | 0.583129 | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | 0.632743 | NaN | 0.808687 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.000000 | 0.902301 | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.902301 | 1.000000 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
Genre latin
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.817225 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.817225 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | 0.642133 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | NaN | NaN | 0.642133 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.000000 | 0.944319 | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.944319 | 1.000000 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
Genre pop
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.849299 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.849299 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.00000 | NaN | 0.649430 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | 0.64943 | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | 0.658568 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | NaN | NaN | 0.658568 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.000000 | 0.837261 | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.837261 | 1.000000 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
Genre r&b
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.814749 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.814749 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | 0.702029 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | NaN | NaN | 0.702029 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.000000 | 0.806013 | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.806013 | 1.000000 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
Genre country
| year | popular | chartrank | acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| popular | NaN | 1.000000 | 0.797394 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| chartrank | NaN | 0.797394 | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| acousticness | NaN | NaN | NaN | 1.000000 | NaN | 0.694685 | NaN | NaN | NaN | NaN | NaN | 0.569462 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| danceability | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| energy | NaN | NaN | NaN | 0.694685 | NaN | 1.000000 | NaN | NaN | 0.512047 | NaN | NaN | 0.775525 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| duration_ms | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| instrumentalness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| valence | NaN | NaN | NaN | NaN | NaN | 0.512047 | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| tempo | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| liveness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| loudness | NaN | NaN | NaN | 0.569462 | NaN | 0.775525 | NaN | NaN | NaN | NaN | NaN | 1.000000 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| speechiness | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key_11 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| explicit_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| mode_0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| mode_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | NaN | NaN | NaN | NaN |
| time_signature_1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
| time_signature_3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.000000 | 0.931865 | NaN |
| time_signature_4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.931865 | 1.000000 | NaN |
| time_signature_5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 |
Since we know ("popularity", "chartrank") & ("energy", "loudness") correlations are present everywhere, we will omit its mention any further in the analysis of the genre feature correlations below.
The Jazz genre's "valence" & "danceability" features are somewhat correlated. There's a correlation between the "valence" & "energy" features; "energy" & "acousticness"; "loudness" & "acousticness"; and "time_signature_3" & "time_signature_4".
Latin genre had a correlation between "time_signature_3" & "time_signature_4".
Pop genre correlations: "energy" & "acousticness"; "time_signature_3" & "time_signature_4".
R&B genre had a correlation between "time_signature_3" & "time_signature_4".
Country genre correlation between the "valence" and "energy" features; "energy" & "acousticness"; "loudness" & "acousticness"; "time_signature_3" & "time_signature_4".
Now that we've analyzed the correlations in our features, let's separate the target feature from the training set.
data_copy = pd.DataFrame(raw_data, copy=True)
Since we know chart rank is correlated to popularity, and we want to base our predictions based on song features, we will drop the 'chartrank' column from our training data
data_copy = data_copy.drop(columns=['chartrank'])
Training data will consist of songs prior to 2019, a total of 20,618 tracks. Test data will consist of songs in 2019 & 2020, summing up to 2,509 tracks. Roughly 12% of our raw data is for testing.
train_matrix = data_copy[data_copy['year'] < 2019]
train_target = train_matrix.pop("popular")
test_matrix = data_copy[data_copy['year'] >= 2019]
test_target = test_matrix.pop("popular")
# Testing on all genres
train_all = pd.DataFrame(train_matrix, copy=True)
train_all = train_all.drop(columns=["genre"])
test_all = pd.DataFrame(test_matrix, copy=True)
test_all = test_all.drop(columns=['genre'])
data_by_genre = data_copy.groupby('genre')
genre_names = []
genres_train = [] # dataframes per genre for years < 2019
genres_train_targets = []
genres_test = [] # dataframes per genre for year >= 2019
genres_test_targets = []
for name, obj in data_by_genre.__iter__():
print("Genre: ", name)
genre_names.append(name)
# Create a copy of the df
copy_genre_matrix = pd.DataFrame(obj, copy=True)
# Drop "genre" column because we want to train/test on numerical values only
copy_genre_matrix = copy_genre_matrix.drop(columns=['genre'])
# Split training & testing data based on year
genre_train = copy_genre_matrix[copy_genre_matrix['year'] < 2019]
genre_test = copy_genre_matrix[copy_genre_matrix['year'] >= 2019]
# Separate target column
genre_train_target = genre_train.pop('popular')
genre_test_target = genre_test.pop('popular')
# Gather newly created training & testing datasets
genres_train.append(genre_train)
genres_train_targets.append(genre_train_target)
genres_test.append(genre_test)
genres_test_targets.append(genre_test_target)
Genre: country Genre: jazz Genre: latin Genre: pop Genre: r&b
Multiple methods will be implemented to test the parameters that yield the highest accuracy per model, as well as visualize the cross-validation score on a more granular level: per-parameter basis.
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
def plot_params(param_values, param_name, train_scores, test_scores):
# plot the training and testing scores in a log scale
plt.plot(param_values, train_scores, label='Train', alpha=0.4, lw=2, c='b')
plt.plot(param_values, test_scores, label='X-Val', alpha=0.4, lw=2, c='g')
plt.legend(loc=7)
plt.xlabel(param_name + " values")
plt.ylabel("Mean cross validation accuracy")
def best_params(x, y, model, params, scoring, k):
grid = GridSearchCV(estimator=model, param_grid=params, scoring=scoring, cv=k, return_train_score=True)
grid.fit(x, y)
return grid
def plot_best_param(x, y, model, param_name, param_values, k):
params = dict([(param_name, param_values)])
grid = GridSearchCV(model, param_grid=params, cv=k, n_jobs=-1, return_train_score=True)
grid.fit(x, y)
print(grid.best_params_)
plot_params(param_values, param_name, grid.cv_results_['mean_train_score'], grid.cv_results_['mean_test_score'])
One of the easiest and most efficient ways to determine feature selection is by using Decision Trees. We will start by analyzing all the features for all the tracks. Then, we will test different parameters and will use the parameters that yield the highest accuracy on our model. Finally, we will see if we could improve our accuracy by repeating this process on a more granular level - separating tracks by genre.
from sklearn import tree
treeclf = tree.DecisionTreeClassifier()
depths = np.arange(1, 15)
splits_parent = np.arange(20, 200, 20)
splits_leaf = np.arange(5, 100, 5)
scoring = 'accuracy'
kfold = 5
parameters = {
'criterion': ['gini', 'entropy'],
'max_depth': depths,
'min_samples_split': splits_parent,
'min_samples_leaf': splits_leaf
}
# WARNING: Takes several minutes to generate
grid = best_params(train_all, train_target, treeclf, parameters, scoring, kfold)
grid.best_estimator_
DecisionTreeClassifier(max_depth=1, min_samples_leaf=5, min_samples_split=20)
grid.best_params_
{'criterion': 'gini',
'max_depth': 1,
'min_samples_leaf': 5,
'min_samples_split': 20}
pd.DataFrame(grid.cv_results_)
| mean_fit_time | std_fit_time | mean_score_time | std_score_time | param_criterion | param_max_depth | param_min_samples_leaf | param_min_samples_split | params | split0_test_score | split1_test_score | split2_test_score | split3_test_score | split4_test_score | mean_test_score | std_test_score | rank_test_score | split0_train_score | split1_train_score | split2_train_score | split3_train_score | split4_train_score | mean_train_score | std_train_score | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.032345 | 0.002663 | 0.004230 | 0.000402 | gini | 1 | 5 | 20 | {'criterion': 'gini', 'max_depth': 1, 'min_sam... | 0.763094 | 0.763094 | 0.763094 | 0.763279 | 0.763037 | 0.763120 | 0.000083 | 1 | 0.763126 | 0.763126 | 0.763126 | 0.763080 | 0.763140 | 0.763120 | 0.000021 |
| 1 | 0.033150 | 0.001362 | 0.004272 | 0.000844 | gini | 1 | 5 | 40 | {'criterion': 'gini', 'max_depth': 1, 'min_sam... | 0.763094 | 0.763094 | 0.763094 | 0.763279 | 0.763037 | 0.763120 | 0.000083 | 1 | 0.763126 | 0.763126 | 0.763126 | 0.763080 | 0.763140 | 0.763120 | 0.000021 |
| 2 | 0.029883 | 0.002545 | 0.003833 | 0.000377 | gini | 1 | 5 | 60 | {'criterion': 'gini', 'max_depth': 1, 'min_sam... | 0.763094 | 0.763094 | 0.763094 | 0.763279 | 0.763037 | 0.763120 | 0.000083 | 1 | 0.763126 | 0.763126 | 0.763126 | 0.763080 | 0.763140 | 0.763120 | 0.000021 |
| 3 | 0.026368 | 0.001619 | 0.003246 | 0.000377 | gini | 1 | 5 | 80 | {'criterion': 'gini', 'max_depth': 1, 'min_sam... | 0.763094 | 0.763094 | 0.763094 | 0.763279 | 0.763037 | 0.763120 | 0.000083 | 1 | 0.763126 | 0.763126 | 0.763126 | 0.763080 | 0.763140 | 0.763120 | 0.000021 |
| 4 | 0.029916 | 0.002995 | 0.003961 | 0.000376 | gini | 1 | 5 | 100 | {'criterion': 'gini', 'max_depth': 1, 'min_sam... | 0.763094 | 0.763094 | 0.763094 | 0.763279 | 0.763037 | 0.763120 | 0.000083 | 1 | 0.763126 | 0.763126 | 0.763126 | 0.763080 | 0.763140 | 0.763120 | 0.000021 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4783 | 0.171409 | 0.009765 | 0.003681 | 0.000198 | entropy | 14 | 95 | 100 | {'criterion': 'entropy', 'max_depth': 14, 'min... | 0.663434 | 0.685984 | 0.715325 | 0.626728 | 0.707495 | 0.679793 | 0.032099 | 3626 | 0.789924 | 0.790409 | 0.789196 | 0.793271 | 0.786178 | 0.789795 | 0.002277 |
| 4784 | 0.171298 | 0.010189 | 0.003586 | 0.000047 | entropy | 14 | 95 | 120 | {'criterion': 'entropy', 'max_depth': 14, 'min... | 0.663434 | 0.685984 | 0.715325 | 0.626728 | 0.707495 | 0.679793 | 0.032099 | 3626 | 0.789924 | 0.790409 | 0.789196 | 0.793271 | 0.786178 | 0.789795 | 0.002277 |
| 4785 | 0.170495 | 0.009711 | 0.003603 | 0.000037 | entropy | 14 | 95 | 140 | {'criterion': 'entropy', 'max_depth': 14, 'min... | 0.663434 | 0.685984 | 0.715325 | 0.626728 | 0.707495 | 0.679793 | 0.032099 | 3626 | 0.789924 | 0.790409 | 0.789196 | 0.793271 | 0.786178 | 0.789795 | 0.002277 |
| 4786 | 0.171007 | 0.009380 | 0.003662 | 0.000111 | entropy | 14 | 95 | 160 | {'criterion': 'entropy', 'max_depth': 14, 'min... | 0.663434 | 0.685984 | 0.715325 | 0.626728 | 0.707495 | 0.679793 | 0.032099 | 3626 | 0.789924 | 0.790409 | 0.789196 | 0.793271 | 0.786178 | 0.789795 | 0.002277 |
| 4787 | 0.169991 | 0.009413 | 0.003610 | 0.000053 | entropy | 14 | 95 | 180 | {'criterion': 'entropy', 'max_depth': 14, 'min... | 0.663434 | 0.685984 | 0.715325 | 0.626728 | 0.707495 | 0.679793 | 0.032099 | 3626 | 0.789924 | 0.790409 | 0.789196 | 0.793271 | 0.786178 | 0.789795 | 0.002277 |
4788 rows × 24 columns
Though we were able to get the best parameters all at once, let's plot one of those parameter ranges to
For now, let's plot the cross-validation against the max depth parameter range.
Later we'll plot the other 2 parameter ranges: min samples split & min samples leaf.
depths2 = np.arange(1, 10)
treeclf2 = tree.DecisionTreeClassifier(criterion='gini', min_samples_split=20, min_samples_leaf=5)
parameters2 = {
'max_depth': depths2
}
grid2 = GridSearchCV(estimator=treeclf2, param_grid=parameters2, n_jobs=-1, cv=5, return_train_score=True)
grid2.fit(train_all, train_target)
plot_params(depths2, 'Max Depths', grid2.cv_results_['mean_train_score'], grid2.cv_results_['mean_test_score'])
grid2.best_params_
{'max_depth': 1}
The plot suggests that a max-depth of 1 is sufficient for returning the highest accuracy. We need to find out which feature the DT is splitting on and analyze its merits. Let's create a Decision Tree model with the suggested min_samples_split & min_samples_leaf values, & set the max_depth at the 3rd highest accuracy rate to get more variance. Them, we'll analyze the classification report to determine how well our model is doing in both precision and recall using those "best" parameters.
dt_all = tree.DecisionTreeClassifier(criterion='entropy', max_depth=7, min_samples_split=140, min_samples_leaf=20)
dt_all.fit(train_all, train_target)
print(dt_all.score(train_all, train_target))
0.7725773595887089
dt_all = tree.DecisionTreeClassifier(criterion='entropy', max_depth=7, min_samples_split=20, min_samples_leaf=5)
dt_all.fit(train_all, train_target)
print(dt_all.score(train_all, train_target))
0.772868367445921
from sklearn.metrics import classification_report
dt_all_pred = dt_all.predict(test_all)
print(classification_report(test_target, dt_all_pred))
precision recall f1-score support
0 0.70 0.99 0.82 1739
1 0.74 0.06 0.12 770
accuracy 0.71 2509
macro avg 0.72 0.53 0.47 2509
weighted avg 0.72 0.71 0.61 2509
As we can see from our low recall score for classifying 'popular', our decision tree model performs worse than randomly guessing at predicting popular track features. The 71% accuracy stems from it's better ability to predict unpopular tracks.
from sklearn.metrics import confusion_matrix
treecm = confusion_matrix(test_target, dt_all_pred)
treecm
array([[1722, 17],
[ 721, 49]])
%matplotlib inline
plt.matshow(treecm)
plt.title('Confusion matrix')
plt.colorbar()
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
Let's see which features were used in our Decision Tree model.
from sklearn.tree import export_graphviz
from IPython.display import Image
def display_model(dot_filename, png_filename, model, columns):
export_graphviz(model, out_file=dot_filename, feature_names=columns)
# system(dot -Tpng DT_all_genres.dot -o dtree.png)
%alias sys_syntax dot -Tpng %s -o %s
%sys_syntax $dot_filename $png_filename
return Image(filename=png_filename, width=800)
display_model('DT_all_genres.dot', 'dtree.png', dt_all, train_all.columns)
dt_all.n_features_
31
Based on all the genres and all the features, our Decision Tree selected 'loudness' as the most informational feature to split on. In the 2nd level, it split on 'acousticness' and 'year'. We can dismiss the 'year' feature since our data aims to predict popularity based on audio features. At the 3rd level, it splits on 'explicit_1', 'danceability', and 'loudness' again.
Using these best params, we can next test on max_features and assign a min_impurity_decrease value to help prune off features that don't return more information.
dt_pruned = tree.DecisionTreeClassifier(criterion='gini', min_samples_split=20, min_samples_leaf=5)
depths = np.arange(1, 7)
n_features = np.arange(1, 15)
split_on_impurity = [0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
parameters = {
'max_depth': depths,
'max_features': n_features,
'min_impurity_decrease': split_on_impurity
}
dt_grid2 = best_params(train_all, train_target, dt_pruned, parameters, scoring, kfold)
dt_grid2.best_params_
{'max_depth': 1, 'max_features': 1, 'min_impurity_decrease': 0.01}
Let's see if our Decision Tree model improves if we fit it on a per-genre basis. We will re-evaluate the previous parameters in order to better fit our smaller datasets. First, we'll observe each parameter range individually for cross-validation scores. Then we'll test on all the parameters to get the best combination of parameters.
genre_dt = tree.DecisionTreeClassifier(criterion='gini')
depths = np.arange(2,10)
plot_best_param(genres_train[0], genres_train_targets[0], genre_dt, 'max_depth', depths, 10)
{'max_depth': 2}
genre_dt = tree.DecisionTreeClassifier(criterion='entropy')
depths = np.arange(2,10)
plot_best_param(genres_train[0], genres_train_targets[0], genre_dt, 'max_depth', depths, 10)
{'max_depth': 2}
genre_dt = tree.DecisionTreeClassifier(criterion='entropy')
splits_parent = np.arange(10, 140, 10)
plot_best_param(genres_train[0], genres_train_targets[0], genre_dt, 'min_samples_split', splits_parent, 10)
{'min_samples_split': 10}
splits_leaf = np.arange(1, 70, 5)
plot_best_param(genres_train[0], genres_train_targets[0], genre_dt, 'min_samples_leaf', splits_leaf, 10)
{'min_samples_leaf': 11}
depths = np.arange(1, 7)
splits_parent = np.arange(10, 100, 10)
splits_leaf = np.arange(1, 40, 5)
parameters = {
'max_depth': depths,
'min_samples_split': splits_parent,
'min_samples_leaf': splits_leaf
}
grid = best_params(genres_train[0], genres_train_targets[0], genre_dt, parameters, scoring, kfold)
grid.best_params_
{'max_depth': 1, 'min_samples_leaf': 1, 'min_samples_split': 10}
depths = np.arange(1, 5)
n_features = np.arange(1, 5)
split_on_impurity = [0.01, 0.05, 0.1, 0.2]
splits_parent = np.arange(5, 105, 25)
splits_leaf = np.arange(1, 40, 5)
parameters = {
'max_depth': depths,
'min_samples_split': splits_parent,
'min_samples_leaf': splits_leaf,
'max_features': n_features,
'min_impurity_decrease': split_on_impurity
}
dt_grid3 = best_params(genres_train[0], genres_train_targets[0], genre_dt, parameters, scoring, kfold)
dt_grid3.best_params_
{'max_depth': 1,
'max_features': 1,
'min_impurity_decrease': 0.01,
'min_samples_leaf': 1,
'min_samples_split': 5}
for name, obj in data_by_genre.__iter__():
print("Genre: ", name)
# Create a copy of the df
copy_genre_matrix = pd.DataFrame(obj, copy=True)
# Drop "genre" column because we want to train/test on numerical values only
copy_genre_matrix = copy_genre_matrix.drop(columns=['genre'])
# Split training & testing data based on year
genre_train = copy_genre_matrix[copy_genre_matrix['year'] < 2019]
genre_test = copy_genre_matrix[copy_genre_matrix['year'] >= 2019]
# Separate target column
genre_train_target = genre_train.pop('popular')
genre_test_target = genre_test.pop('popular')
# Create a classifier with the best params
dt_per_genre = tree.DecisionTreeClassifier(criterion='entropy', max_depth=5, min_samples_split=5, min_samples_leaf=1, min_impurity_decrease=0.01, max_features=0.5)
# Fit the classifier with our data per genre
dt_per_genre.fit(genre_train, genre_train_target)
print("Number of features used: ", dt_per_genre.max_features_)
# Predict on test set
dt_predict_per_genre = dt_per_genre.predict(genre_test)
#print("Predictions on test set:")
#display(dt_predict_per_genre)
# Analyze how well our Decision Tree can predict popularity
print(classification_report(genre_test_target, dt_predict_per_genre))
# Confusion matrix
dt_genre_cm = confusion_matrix(genre_test_target, dt_predict_per_genre)
# Plot the confusion matrix
%matplotlib inline
plt.matshow(dt_genre_cm)
plt.title('Confusion matrix')
plt.colorbar()
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
# Display Tree
if name == "r&b":
name = "rnb"
dot_filename = f'{name}_DT.dot'
png_filename = f'{name}_tree.png'
display(display_model(dot_filename, png_filename, dt_per_genre, genre_train.columns))
Genre: country
Number of features used: 15
precision recall f1-score support
0 0.62 1.00 0.77 321
1 0.00 0.00 0.00 197
accuracy 0.62 518
macro avg 0.31 0.50 0.38 518
weighted avg 0.38 0.62 0.47 518
/opt/anaconda3/lib/python3.8/site-packages/sklearn/metrics/_classification.py:1221: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. _warn_prf(average, modifier, msg_start, len(result))
Genre: jazz
Number of features used: 15
precision recall f1-score support
0 0.92 0.90 0.91 357
1 0.66 0.70 0.68 96
accuracy 0.86 453
macro avg 0.79 0.80 0.79 453
weighted avg 0.86 0.86 0.86 453
Genre: latin
Number of features used: 15
precision recall f1-score support
0 0.63 1.00 0.78 325
1 0.00 0.00 0.00 188
accuracy 0.63 513
macro avg 0.32 0.50 0.39 513
weighted avg 0.40 0.63 0.49 513
/opt/anaconda3/lib/python3.8/site-packages/sklearn/metrics/_classification.py:1221: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. _warn_prf(average, modifier, msg_start, len(result))
Genre: pop
Number of features used: 15
precision recall f1-score support
0 0.78 1.00 0.88 353
1 0.00 0.00 0.00 97
accuracy 0.78 450
macro avg 0.39 0.50 0.44 450
weighted avg 0.62 0.78 0.69 450
/opt/anaconda3/lib/python3.8/site-packages/sklearn/metrics/_classification.py:1221: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. _warn_prf(average, modifier, msg_start, len(result))
Genre: r&b
Number of features used: 15
precision recall f1-score support
0 0.79 0.84 0.81 383
1 0.63 0.55 0.59 192
accuracy 0.74 575
macro avg 0.71 0.69 0.70 575
weighted avg 0.74 0.74 0.74 575
Overall, our accuracy only improved in the Jazz, Pop, & R&B genres compared to the DT model based on all audio features across all genres. Only in the R&B genre did we improve our recall score, which was still no better than guessing.
First, we'll test on all the tracks for all genres using K Nearest Neighbor as our classifier with Euclidean distance as our distance metric.
Then, we will do a grid search on the best 'k'.
Later, we will analyze the classifier more granularly, on a genre-by-genre case.
from sklearn import feature_selection
from sklearn.neighbors import KNeighborsClassifier
Let's evaluate the best number of nearest neighbors to optimize our knn prediction.
ks = np.arange(1,20)
parameters = {
'n_neighbors': ks,
'weights': ['distance'],
'p': [2]
}
kfold = 5
scoring = 'accuracy'
knn = KNeighborsClassifier()
grid = best_params(train_all, train_target, knn, parameters, scoring, kfold)
# Plot the error values on the training and cross-validation
# splits across the specified values of the main parameter to test on.
plot_params(ks, 'Neighbors', grid.cv_results_['mean_train_score'], grid.cv_results_['mean_test_score'])
The elbow is at roughly 7 neighbors.
knn = KNeighborsClassifier(n_neighbors=7, weights='distance', p=2)
knn.fit(train_all, train_target)
knnpreds_test = knn.predict(test_all)
Let's evaluate our classifier's accuracy on its 2019-2020 popularity predictions based on audio features:
print(classification_report(test_target, knnpreds_test))
precision recall f1-score support
0 0.72 0.83 0.77 1739
1 0.41 0.28 0.33 770
accuracy 0.66 2509
macro avg 0.57 0.55 0.55 2509
weighted avg 0.63 0.66 0.63 2509
Though our f1-score is worse than the f1-score of our decision tree, our recall for predicted popularity is much higher!
Since we don't have too many features, we'll start with a Backward-SFS to find features that will give us the most information when attempting to predict popularity. We'll start by using the K Nearest Neighbors classifier as our model to test on for finding the elbow of a sequentially ordered k-valued array for our Backward Feature Selection model to choose on.
Unable to use the SequentialFeatureSelector method because it was introduced in scikit-learn version 0.24. Anaconda's environment is running on version 0.23.3, without an option to update.
https://scikit-learn.org/stable/modules/feature_selection.html
from sklearn.feature_selection import SequentialFeatureSelector
knn = KNeighborsClassifier(n_neighbors=5)
sfs = feature_selection.SequentialFeatureSelector(knn, n_features_to_select=5)
sfs.fit(train_all, train_target)
sfs.get_params()
--------------------------------------------------------------------------- ImportError Traceback (most recent call last) <ipython-input-57-11d76c26e7d1> in <module> ----> 1 from sklearn.feature_selection import SequentialFeatureSelector 2 knn = KNeighborsClassifier(n_neighbors=5) 3 sfs = feature_selection.SequentialFeatureSelector(knn, n_features_to_select=5) 4 sfs.fit(train_all, train_target) 5 sfs.get_params() ImportError: cannot import name 'SequentialFeatureSelector' from 'sklearn.feature_selection' (/opt/anaconda3/lib/python3.8/site-packages/sklearn/feature_selection/__init__.py)
from sklearn import naive_bayes
Training on tracks across all genres for popularity
# let's make a copy of train_all, test_all that drops the year column
train_all_no_year = pd.DataFrame(train_all, copy=True)
train_all_no_year = train_all_no_year.drop(columns=['year'])
test_all_no_year = pd.DataFrame(test_all, copy=True)
test_all_no_year = test_all_no_year.drop(columns=['year'])
# Create & fit our classifier
nb = naive_bayes.GaussianNB().fit(train_all_no_year, train_target)
# Get accuracy scores
print ("Score on Training: ", nb.score(train_all_no_year, train_target))
print ("Score on Test: ", nb.score(test_all_no_year, test_target))
nb_predict = nb.predict(test_all_no_year)
print(classification_report(test_target, nb_predict))
Score on Training: 0.624017848481909
Score on Test: 0.5914707054603427
precision recall f1-score support
0 0.78 0.57 0.66 1739
1 0.40 0.64 0.49 770
accuracy 0.59 2509
macro avg 0.59 0.61 0.57 2509
weighted avg 0.66 0.59 0.61 2509
Training on tracks per genres for popularity prediction
for name, obj in data_by_genre.__iter__():
print("Genre: ", name)
# Create a copy of the df
copy_genre_matrix = pd.DataFrame(obj, copy=True)
# Drop categorical columns that don't contribute to information that would lead to better predictions.
copy_genre_matrix = copy_genre_matrix.drop(columns=['genre'])
# Split training & testing data based on year
genre_train = copy_genre_matrix[copy_genre_matrix['year'] < 2019]
genre_test = copy_genre_matrix[copy_genre_matrix['year'] >= 2019]
genre_train= genre_train.drop(columns=['year'])
genre_test= genre_test.drop(columns=['year'])
# Separate target column
genre_train_target = genre_train.pop('popular')
genre_test_target = genre_test.pop('popular')
# Create & fit our classifier with our data per genre
nb_per_genre = naive_bayes.GaussianNB().fit(genre_train, genre_train_target)
print(nb_per_genre)
print ("Score on Training: ", nb_per_genre.score(genre_train, genre_train_target))
print ("Score on Test: ", nb_per_genre.score(genre_test, genre_test_target))
# Predict on test set
nb_predict_genre = nb_per_genre.predict(genre_test)
# Analyze how well our Decision Tree can predict a genre
print(classification_report(genre_test_target, nb_predict_genre))
print()
Genre: country
GaussianNB()
Score on Training: 0.4773750296138356
Score on Test: 0.5154440154440154
precision recall f1-score support
0 0.86 0.26 0.40 321
1 0.44 0.93 0.59 197
accuracy 0.52 518
macro avg 0.65 0.60 0.50 518
weighted avg 0.70 0.52 0.47 518
Genre: jazz
GaussianNB()
Score on Training: 0.3614080834419817
Score on Test: 0.5320088300220751
precision recall f1-score support
0 0.99 0.41 0.58 357
1 0.31 0.98 0.47 96
accuracy 0.53 453
macro avg 0.65 0.70 0.53 453
weighted avg 0.84 0.53 0.56 453
Genre: latin
GaussianNB()
Score on Training: 0.5986653956148713
Score on Test: 0.5789473684210527
precision recall f1-score support
0 0.70 0.59 0.64 325
1 0.44 0.56 0.50 188
accuracy 0.58 513
macro avg 0.57 0.58 0.57 513
weighted avg 0.61 0.58 0.59 513
Genre: pop
GaussianNB()
Score on Training: 0.3225458468176915
Score on Test: 0.4577777777777778
precision recall f1-score support
0 0.97 0.32 0.48 353
1 0.28 0.96 0.43 97
accuracy 0.46 450
macro avg 0.62 0.64 0.46 450
weighted avg 0.82 0.46 0.47 450
Genre: r&b
GaussianNB()
Score on Training: 0.6444826105624731
Score on Test: 0.6869565217391305
precision recall f1-score support
0 0.89 0.60 0.72 383
1 0.52 0.85 0.65 192
accuracy 0.69 575
macro avg 0.71 0.73 0.68 575
weighted avg 0.77 0.69 0.69 575
Training on tracks per genres for genre prediction
# Make a copy of train_all, test_all that drops the year column
train_all_genres = pd.DataFrame(train_matrix, copy=True)
train_all_genres = train_all_genres.drop(columns=['year'])
train_target_genres = train_all_genres.pop('genre')
# Make 'genre' our target
test_all_genres = pd.DataFrame(test_matrix, copy=True)
test_all_genres = test_all_genres.drop(columns=['year'])
test_target_genres = test_all_genres.pop('genre')
# Create & fit our classifier
nb = naive_bayes.GaussianNB().fit(train_all_genres, train_target_genres)
# Get accuracy scores
print ("Score on Training: ", nb.score(train_all_genres, train_target_genres))
print ("Score on Test: ", nb.score(test_all_genres, test_target_genres))
nb_predict = nb.predict(test_all_genres)
print(classification_report(test_target_genres, nb_predict))
Score on Training: 0.48001746047143273
Score on Test: 0.5420486249501794
precision recall f1-score support
country 0.52 0.77 0.62 518
jazz 0.73 0.85 0.79 453
latin 0.48 0.35 0.40 513
pop 0.43 0.10 0.16 450
r&b 0.47 0.62 0.54 575
accuracy 0.54 2509
macro avg 0.53 0.54 0.50 2509
weighted avg 0.52 0.54 0.50 2509
In conclusion, out of all of our classification models, Naive Bayes scored the highest in terms of recall. For track prediction, it scored 57% on predicted unpopularity for tracks across all genres & 64% on predicting popularity. In predicting a track's genre, it scored high in the country and jazz genres, mediocre in r&b, and poorly in lating and pop. Averaging that out, the data we are passing into our models is only returning scores slightly better than random guessing.
So far, our models have failed to return a satisfactory accuracy score to predict audio features that would indicate a 'popular' track. Instead, we may find better luck in detecting a genre based on audio features. We will use the density based clustering method (DBSCAN) to predict a track's genre. DBSCAN is useful in detecting outliers as well, which will be interesting to visualize if our results are meaningful.
We use DBSCAN instead of kMeans because
We remove the 'year' feature since it should be irrelavant to genre prediction.
Our classification methods proved 'duration' to be more useful than we had initially imagined, in particular with predicting popularity within the pop, latin, & jazz genres. This makes sense for the Jazz genre, but we're not sure why that would also apply to the Latin & Pop genres. Thus, we shall keep this feature in the data to see if it'll add any more insights to our findings.
# We want all the raw_data, except for the popular, chartrank, & year columns.
X = train_matrix.drop(columns=['year'])
# Our target will be the genre feature this time
labels_true = X.pop('genre')
X = X.values
labels_true = labels_true.values
from sklearn.cluster import DBSCAN
from sklearn import metrics
Code source below provided by scikit-learn's DBSCAN demo: https://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html#sphx-glr-auto-examples-cluster-plot-dbscan-py
def d_cluster_analysis(X, labels_true, epsilons, minSamples):
est_clusters = []
h_scores = [] # Homogeneity
c_scores = [] # Completeness
v_scores = [] # Homogeniety + Completeness score
for e in epsilons:
for m in minSamples:
# Compute DBSCAN
dbs = DBSCAN(eps=e, min_samples=m, n_jobs=-1).fit(X)
core_samples_mask = np.zeros_like(dbs.labels_, dtype=bool)
core_samples_mask[dbs.core_sample_indices_] = True
labels = dbs.labels_
print(f'DBSCAN with epsilon value of {e}:')
# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
n_noise_ = list(labels).count(-1)
est_clusters.append(n_clusters_)
print('Estimated number of clusters: %d' % n_clusters_)
print('Estimated number of noise points: %d' % n_noise_)
# Accuracy Scores
hscore = metrics.homogeneity_score(labels_true, labels)
h_scores.append(hscore)
print("Homogeneity: %0.3f" % hscore)
cscore = metrics.completeness_score(labels_true, labels)
c_scores.append(cscore)
print("Completeness: %0.3f" % cscore)
vscore = metrics.v_measure_score(labels_true, labels)
v_scores.append(vscore)
print("V-measure (Combined Homogeneity & Completeness scores): %0.3f" % vscore)
print("Adjusted Rand Index: %0.3f"
% metrics.adjusted_rand_score(labels_true, labels))
print("Adjusted Mutual Information: %0.3f"
% metrics.adjusted_mutual_info_score(labels_true, labels))
print("Silhouette Coefficient: %0.3f"
% metrics.silhouette_score(X, labels))
# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
if k == -1:
# Black used for noise.
col = [0, 0, 0, 1]
class_member_mask = (labels == k)
xy = X[class_member_mask & core_samples_mask]
plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col), markeredgecolor='k', markersize=14)
xy = X[class_member_mask & ~core_samples_mask]
plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
markeredgecolor='k', markersize=6)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
print()
print(est_clusters)
print(h_scores)
print(c_scores)
print(v_scores)
return est_clusters, h_scores, c_scores, v_scores
eps = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
est_clusters, h_scores, c_scores, v_scores = d_cluster_analysis(X, labels_true, eps, [10])
DBSCAN with epsilon value of 0.2: Estimated number of clusters: 54 Estimated number of noise points: 14118 Homogeneity: 0.061 Completeness: 0.062 V-measure (Combined Homogeneity & Completeness scores): 0.062 Adjusted Rand Index: 0.022 Adjusted Mutual Information: 0.058 Silhouette Coefficient: -0.315
DBSCAN with epsilon value of 0.3: Estimated number of clusters: 71 Estimated number of noise points: 5793 Homogeneity: 0.103 Completeness: 0.054 V-measure (Combined Homogeneity & Completeness scores): 0.071 Adjusted Rand Index: 0.037 Adjusted Mutual Information: 0.068 Silhouette Coefficient: 0.170
DBSCAN with epsilon value of 0.4: Estimated number of clusters: 76 Estimated number of noise points: 2339 Homogeneity: 0.103 Completeness: 0.047 V-measure (Combined Homogeneity & Completeness scores): 0.064 Adjusted Rand Index: 0.019 Adjusted Mutual Information: 0.062 Silhouette Coefficient: 0.389
DBSCAN with epsilon value of 0.5: Estimated number of clusters: 69 Estimated number of noise points: 1110 Homogeneity: 0.092 Completeness: 0.041 V-measure (Combined Homogeneity & Completeness scores): 0.057 Adjusted Rand Index: 0.012 Adjusted Mutual Information: 0.054 Silhouette Coefficient: 0.485
DBSCAN with epsilon value of 0.6: Estimated number of clusters: 70 Estimated number of noise points: 708 Homogeneity: 0.087 Completeness: 0.039 V-measure (Combined Homogeneity & Completeness scores): 0.053 Adjusted Rand Index: 0.011 Adjusted Mutual Information: 0.051 Silhouette Coefficient: 0.513
DBSCAN with epsilon value of 0.7: Estimated number of clusters: 72 Estimated number of noise points: 555 Homogeneity: 0.087 Completeness: 0.038 V-measure (Combined Homogeneity & Completeness scores): 0.053 Adjusted Rand Index: 0.010 Adjusted Mutual Information: 0.050 Silhouette Coefficient: 0.519
DBSCAN with epsilon value of 0.8: Estimated number of clusters: 72 Estimated number of noise points: 492 Homogeneity: 0.086 Completeness: 0.038 V-measure (Combined Homogeneity & Completeness scores): 0.053 Adjusted Rand Index: 0.010 Adjusted Mutual Information: 0.050 Silhouette Coefficient: 0.522
DBSCAN with epsilon value of 0.9: Estimated number of clusters: 74 Estimated number of noise points: 430 Homogeneity: 0.087 Completeness: 0.038 V-measure (Combined Homogeneity & Completeness scores): 0.053 Adjusted Rand Index: 0.010 Adjusted Mutual Information: 0.050 Silhouette Coefficient: 0.524
[54, 71, 76, 69, 70, 72, 72, 74] [0.061036200229735806, 0.10345029825178977, 0.10305321661715675, 0.09190872395054833, 0.08745510010300099, 0.0865661386523767, 0.08638213167360077, 0.08662062289728509] [0.06210488276024812, 0.05404564243594596, 0.04687669205815739, 0.04081826164272435, 0.03851067273926526, 0.03797291942866461, 0.03782782853290429, 0.037838923500153346] [0.061565904202858054, 0.07099913565764139, 0.06444069690493225, 0.056530393193116514, 0.05347412496986292, 0.05278936678898358, 0.05261491847872919, 0.05266982273709236]
def plot_clustering_params(param_values, param_name, h_scores, c_scores, v_scores):
plt.plot(param_values, h_scores, label='Homogeneity Score', alpha=0.4, lw=2, c='b')
plt.plot(param_values, c_scores, label='Completeness Score', alpha=0.4, lw=2, c='g')
plt.plot(param_values, v_scores, label='V-Measure', alpha=0.4, lw=2, c='r')
plt.legend(loc=7)
plt.xlabel(param_name + " values")
plt.ylabel("Accuracy Scores")
plot_clustering_params(eps, 'Epsilons', h_scores, c_scores, v_scores)
plt.plot(eps, est_clusters, alpha=0.4, lw=2, c='r')
plt.xlabel("Epsilon values")
plt.ylabel("Estimated Cluster size")
Text(0, 0.5, 'Estimated Cluster size')
DBSCAN with epsilon value of 0.1 returned 0 clusters, with all points considered "noise points".
DBSCAN with epsilon value of 0.2 returned 54 clusters, with 14,118 considered "noise points".
DBSCAN with epsilon value of 0.3 returned 71 clusters, with 5,793 considered "noise points".
DBSCAN with epsilon value of 0.4 returned 76 clusters, with 2,339 considered "noise points".
DBSCAN with epsilon value of 0.5 returned 69 clusters, with 1,110 considered "noise points".
DBSCAN with epsilon value of 0.6 returned 70 clusters, with 708 considered "noise points".
DBSCAN with epsilon value of 0.7 returned 72 clusters, with 555 considered "noise points".
DBSCAN with epsilon value of 0.8 returned 72 clusters, with 492 considered "noise points".
DBSCAN with epsilon value of 0.9 returned 74 clusters, with 430 considered "noise points".
A small min_sample of 10 returned an average cluster of 62. The range of cluster size for that min sample across an epsilon value between 0.0 & 1.0 was 54 to 74.
We know we have at least 3,000 track samples per genre, so let's increase our min_sample to 50. We chose 50 because at 100 we were getting errors.
eps = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
est_clusters, h_scores, c_scores, v_scores = d_cluster_analysis(X, labels_true, eps, [50])
DBSCAN with epsilon value of 0.2: Estimated number of clusters: 7 Estimated number of noise points: 19982 Homogeneity: 0.007 Completeness: 0.062 V-measure (Combined Homogeneity & Completeness scores): 0.013 Adjusted Rand Index: 0.000 Adjusted Mutual Information: 0.013 Silhouette Coefficient: -0.253
DBSCAN with epsilon value of 0.3: Estimated number of clusters: 21 Estimated number of noise points: 11388 Homogeneity: 0.063 Completeness: 0.052 V-measure (Combined Homogeneity & Completeness scores): 0.057 Adjusted Rand Index: 0.034 Adjusted Mutual Information: 0.056 Silhouette Coefficient: 0.030
DBSCAN with epsilon value of 0.4: Estimated number of clusters: 34 Estimated number of noise points: 6070 Homogeneity: 0.084 Completeness: 0.047 V-measure (Combined Homogeneity & Completeness scores): 0.060 Adjusted Rand Index: 0.040 Adjusted Mutual Information: 0.059 Silhouette Coefficient: 0.286
DBSCAN with epsilon value of 0.5: Estimated number of clusters: 42 Estimated number of noise points: 3475 Homogeneity: 0.087 Completeness: 0.043 V-measure (Combined Homogeneity & Completeness scores): 0.058 Adjusted Rand Index: 0.027 Adjusted Mutual Information: 0.056 Silhouette Coefficient: 0.409
DBSCAN with epsilon value of 0.6: Estimated number of clusters: 46 Estimated number of noise points: 2077 Homogeneity: 0.083 Completeness: 0.039 V-measure (Combined Homogeneity & Completeness scores): 0.053 Adjusted Rand Index: 0.015 Adjusted Mutual Information: 0.051 Silhouette Coefficient: 0.465
DBSCAN with epsilon value of 0.7: Estimated number of clusters: 51 Estimated number of noise points: 1327 Homogeneity: 0.081 Completeness: 0.037 V-measure (Combined Homogeneity & Completeness scores): 0.051 Adjusted Rand Index: 0.011 Adjusted Mutual Information: 0.049 Silhouette Coefficient: 0.491
DBSCAN with epsilon value of 0.8: Estimated number of clusters: 52 Estimated number of noise points: 1100 Homogeneity: 0.082 Completeness: 0.037 V-measure (Combined Homogeneity & Completeness scores): 0.051 Adjusted Rand Index: 0.011 Adjusted Mutual Information: 0.049 Silhouette Coefficient: 0.499
DBSCAN with epsilon value of 0.9: Estimated number of clusters: 53 Estimated number of noise points: 1013 Homogeneity: 0.082 Completeness: 0.037 V-measure (Combined Homogeneity & Completeness scores): 0.051 Adjusted Rand Index: 0.011 Adjusted Mutual Information: 0.049 Silhouette Coefficient: 0.503
DBSCAN with epsilon value of 1.0: Estimated number of clusters: 53 Estimated number of noise points: 981 Homogeneity: 0.082 Completeness: 0.037 V-measure (Combined Homogeneity & Completeness scores): 0.051 Adjusted Rand Index: 0.011 Adjusted Mutual Information: 0.049 Silhouette Coefficient: 0.504
[7, 21, 34, 42, 46, 51, 52, 53, 53] [0.007439437340387316, 0.06275957121881402, 0.0835926988048693, 0.08718225335218391, 0.08284850580060302, 0.08149570728125913, 0.08169162824849499, 0.08195155006595937, 0.08194543765055488] [0.06186548383928809, 0.051941456026674646, 0.04679286115605084, 0.0428973515461644, 0.038782853529784445, 0.03713284674804457, 0.03697045082122138, 0.03695359891237708, 0.036913406701161874] [0.013281723223143948, 0.056840354214756125, 0.0599996126872978, 0.05750152414066704, 0.0528334384046228, 0.051019210911918716, 0.05090381608587978, 0.05093815932120488, 0.05089878306991877]
plot_clustering_params(eps, 'Epsilons', h_scores, c_scores, v_scores)
As we see in the plot, our accuracy scores did not improve. The last epsilon value of 2.0 with the accuracy score of 100% was because it clustered all points into 1 cluster, making that score invalid. Epsilons > 2.0 were thus not calculated.
eps = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
plt.plot(eps, est_clusters, alpha=0.4, lw=2, c='r')
plt.xlabel("Epsilon values")
plt.ylabel("Estimated Cluster size")
Text(0, 0.5, 'Estimated Cluster size')
A lower epsilon value returned cluster sizes closer to our target cluster size of 5, however, it considered all other points as noise. This leads us to believe we may have too much data.
Tracks per genre in train sample:
Next, we will test clustering on a smaller sample size - our test data. Our theory is that by reducing our sample size, we might get better completeness and homogeneity scores.
Tracks per genre in test sample:
# All the raw test data (tracks in years >= 2019) except for the popular, chartrank, & year columns.
X = test_matrix.drop(columns=['year'])
labels_true = X.pop('genre')
X = X.values
labels_true = labels_true.values
eps = [0.5, 0.6, 0.7, 0.8, 0.9, 1.0] # Error: 0 clusters at eps < 0.5 & eps >=2.0 &
est_clusters, h_scores, c_scores, v_scores = d_cluster_analysis(X, labels_true, eps, [50])
DBSCAN with epsilon value of 0.5: Estimated number of clusters: 7 Estimated number of noise points: 1979 Homogeneity: 0.047 Completeness: 0.082 V-measure (Combined Homogeneity & Completeness scores): 0.060 Adjusted Rand Index: 0.017 Adjusted Mutual Information: 0.056 Silhouette Coefficient: -0.016
DBSCAN with epsilon value of 0.6: Estimated number of clusters: 11 Estimated number of noise points: 1647 Homogeneity: 0.070 Completeness: 0.077 V-measure (Combined Homogeneity & Completeness scores): 0.073 Adjusted Rand Index: 0.030 Adjusted Mutual Information: 0.068 Silhouette Coefficient: 0.047
DBSCAN with epsilon value of 0.7: Estimated number of clusters: 13 Estimated number of noise points: 1449 Homogeneity: 0.081 Completeness: 0.075 V-measure (Combined Homogeneity & Completeness scores): 0.078 Adjusted Rand Index: 0.038 Adjusted Mutual Information: 0.072 Silhouette Coefficient: 0.115
DBSCAN with epsilon value of 0.8: Estimated number of clusters: 15 Estimated number of noise points: 1294 Homogeneity: 0.085 Completeness: 0.069 V-measure (Combined Homogeneity & Completeness scores): 0.076 Adjusted Rand Index: 0.042 Adjusted Mutual Information: 0.069 Silhouette Coefficient: 0.153
DBSCAN with epsilon value of 0.9: Estimated number of clusters: 15 Estimated number of noise points: 1249 Homogeneity: 0.079 Completeness: 0.062 V-measure (Combined Homogeneity & Completeness scores): 0.070 Adjusted Rand Index: 0.040 Adjusted Mutual Information: 0.063 Silhouette Coefficient: 0.164
DBSCAN with epsilon value of 1.0: Estimated number of clusters: 17 Estimated number of noise points: 1092 Homogeneity: 0.082 Completeness: 0.058 V-measure (Combined Homogeneity & Completeness scores): 0.068 Adjusted Rand Index: 0.040 Adjusted Mutual Information: 0.061 Silhouette Coefficient: 0.199
[7, 11, 13, 15, 15, 17] [0.04712224932640945, 0.06971606461753649, 0.08121566952286992, 0.08462009185966173, 0.07891857585412414, 0.08194968562140026] [0.08203254344141314, 0.07689377292429238, 0.0745519061842673, 0.0685412474242644, 0.062348620522711194, 0.058323948551103566] [0.059859303430957814, 0.07312921604386458, 0.07774124938999133, 0.07573669282775393, 0.06966181058759131, 0.06814722205149162]
param_name = 'eps'
plot_clustering_params(eps, param_name, h_scores, c_scores, v_scores)
plt.plot(eps, est_clusters, alpha=0.4, lw=2, c='r')
plt.xlabel(param_name + " values")
plt.ylabel("Estimated Cluster size")
Text(0, 0.5, 'Estimated Cluster size')
An epsilon value of 0.7 gave us the best v-measure at 0.078 (combination of homogeneity & completeness). However, that is still a poor score and estimated 13 clusters, whereas an epsilon of 0.5 gave us the closes number of clusters to the true data at size 7.
eps = [0.7, 0.8, 0.9, 1.0, 1.5] # Error: 0 clusters at eps < 0.7 & eps >=1.5
est_clusters, h_scores, c_scores, v_scores = d_cluster_analysis(X, labels_true, eps, [100])
DBSCAN with epsilon value of 0.7: Estimated number of clusters: 2 Estimated number of noise points: 2286 Homogeneity: 0.010 Completeness: 0.046 V-measure (Combined Homogeneity & Completeness scores): 0.017 Adjusted Rand Index: 0.002 Adjusted Mutual Information: 0.015 Silhouette Coefficient: -0.034
DBSCAN with epsilon value of 0.8: Estimated number of clusters: 2 Estimated number of noise points: 2264 Homogeneity: 0.008 Completeness: 0.032 V-measure (Combined Homogeneity & Completeness scores): 0.013 Adjusted Rand Index: 0.002 Adjusted Mutual Information: 0.011 Silhouette Coefficient: -0.026
DBSCAN with epsilon value of 0.9: Estimated number of clusters: 2 Estimated number of noise points: 2252 Homogeneity: 0.007 Completeness: 0.027 V-measure (Combined Homogeneity & Completeness scores): 0.011 Adjusted Rand Index: 0.003 Adjusted Mutual Information: 0.009 Silhouette Coefficient: -0.020
DBSCAN with epsilon value of 1.0: Estimated number of clusters: 3 Estimated number of noise points: 2130 Homogeneity: 0.011 Completeness: 0.031 V-measure (Combined Homogeneity & Completeness scores): 0.017 Adjusted Rand Index: 0.006 Adjusted Mutual Information: 0.014 Silhouette Coefficient: -0.000
DBSCAN with epsilon value of 1.5: Estimated number of clusters: 1 Estimated number of noise points: 34 Homogeneity: 0.004 Completeness: 0.084 V-measure (Combined Homogeneity & Completeness scores): 0.007 Adjusted Rand Index: 0.001 Adjusted Mutual Information: 0.006 Silhouette Coefficient: 0.192
[2, 2, 2, 3, 1] [0.010408282127825342, 0.007790832849119033, 0.006722874629092337, 0.011376996036882357, 0.003748418614086435] [0.046212977434359453, 0.032272240807039734, 0.026886138517193146, 0.03098448962739205, 0.0838626536219218] [0.01699000378383951, 0.0125515898231894, 0.010756170538228197, 0.01664296755262065, 0.007176086853869041]
plot_clustering_params(eps, param_name, h_scores, c_scores, v_scores)
plt.plot(eps, est_clusters, alpha=0.4, lw=2, c='r')
plt.xlabel(param_name + " values")
plt.ylabel("Estimated Cluster size")
Text(0, 0.5, 'Estimated Cluster size')
In conclusion, higher min samples gave us better results, but the results were still poor. Minimizing our sample size did not seem to have helped either. The preferred epsilon value was around 0.7.
We use kMeans to explore how well kMeans could predict a song's genre based on its features.
from sklearn.cluster import KMeans
X = train_matrix.drop(columns=['year'])
X_labels_true = X.pop('genre')
X = X.values
X_labels_true = X_labels_true.values
kmeans = KMeans(n_clusters=5, random_state=33, n_jobs=-1).fit(X)
/opt/anaconda3/lib/python3.8/site-packages/sklearn/cluster/_kmeans.py:938: FutureWarning: 'n_jobs' was deprecated in version 0.23 and will be removed in 0.25.
warnings.warn("'n_jobs' was deprecated in version 0.23 and will be"
clusters = kmeans.predict(X)
X_columns = ['acousticness', 'danceability', 'energy',
'duration_ms', 'instrumentalness', 'valence', 'tempo', 'liveness',
'loudness', 'speechiness', 'key_0', 'key_1', 'key_2', 'key_3', 'key_4',
'key_5', 'key_6', 'key_7', 'key_8', 'key_9', 'key_10', 'key_11',
'explicit_0', 'explicit_1', 'mode_0', 'mode_1', 'time_signature_1',
'time_signature_3', 'time_signature_4', 'time_signature_5']
centroids = pd.DataFrame(kmeans.cluster_centers_, columns=X_columns)
centroids
| acousticness | danceability | energy | duration_ms | instrumentalness | valence | tempo | liveness | loudness | speechiness | key_0 | key_1 | key_2 | key_3 | key_4 | key_5 | key_6 | key_7 | key_8 | key_9 | key_10 | key_11 | explicit_0 | explicit_1 | mode_0 | mode_1 | time_signature_1 | time_signature_3 | time_signature_4 | time_signature_5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.504409 | 0.516571 | 0.462668 | 0.129211 | 0.113463 | 0.443026 | 0.499813 | 0.186671 | 0.776242 | 0.066524 | 1.368876e-01 | 7.636888e-02 | 1.023055e-01 | 5.259366e-02 | 7.708934e-02 | 9.365994e-02 | 5.331412e-02 | 1.311239e-01 | 6.340058e-02 | 9.221902e-02 | 7.636888e-02 | 4.466859e-02 | 9.733429e-01 | 2.665706e-02 | 2.096542e-01 | 7.903458e-01 | 0.019452 | 9.524496e-01 | -1.332268e-15 | 0.028098 |
| 1 | 0.291985 | 0.602712 | 0.637462 | 0.130788 | 0.069941 | 0.542770 | 0.465865 | 0.191064 | 0.828252 | 0.061618 | -7.910339e-16 | 1.171850e-01 | 1.388388e-01 | 3.619573e-02 | 7.419595e-02 | 8.725188e-02 | 6.634115e-02 | 1.568836e-01 | 9.277147e-02 | 1.045537e-01 | 6.368751e-02 | 6.209532e-02 | 1.000000e+00 | 1.831868e-15 | 5.162537e-15 | 1.000000e+00 | 0.003078 | -1.512679e-15 | 9.926759e-01 | 0.004246 |
| 2 | 0.274663 | 0.643010 | 0.647505 | 0.136881 | 0.142344 | 0.569852 | 0.446986 | 0.190841 | 0.823732 | 0.081171 | 7.539248e-02 | 8.652793e-02 | 5.713764e-02 | 3.358890e-02 | 9.510770e-02 | 1.328952e-01 | 8.050383e-02 | 8.251187e-02 | 4.289887e-02 | 1.013143e-01 | 9.200438e-02 | 1.201168e-01 | 1.000000e+00 | -8.604228e-16 | 1.000000e+00 | -5.329071e-15 | 0.005659 | 9.714451e-16 | 9.828405e-01 | 0.011501 |
| 3 | 0.312843 | 0.606061 | 0.620549 | 0.132344 | 0.083578 | 0.550268 | 0.465079 | 0.202760 | 0.821343 | 0.058135 | 1.000000e+00 | 2.359224e-16 | 2.081668e-16 | -1.873501e-16 | 5.412337e-16 | 4.163336e-16 | 6.106227e-16 | 4.163336e-16 | -3.608225e-16 | 1.387779e-17 | -4.857226e-16 | -2.081668e-16 | 1.000000e+00 | -7.216450e-16 | 2.498002e-15 | 1.000000e+00 | 0.005788 | 3.469447e-16 | 9.864952e-01 | 0.007717 |
| 4 | 0.187129 | 0.690910 | 0.642168 | 0.134651 | 0.006424 | 0.489783 | 0.465474 | 0.195476 | 0.845368 | 0.165754 | 9.726225e-02 | 1.772334e-01 | 7.096542e-02 | 2.881844e-02 | 4.178674e-02 | 6.412104e-02 | 8.357349e-02 | 8.825648e-02 | 9.365994e-02 | 8.357349e-02 | 6.808357e-02 | 1.026657e-01 | -1.199041e-14 | 1.000000e+00 | 4.499280e-01 | 5.500720e-01 | 0.004683 | 1.765130e-02 | 9.528098e-01 | 0.024856 |
def cluster_sizes(clusters, data):
#clusters is an array of cluster labels for each instance in the data
size = {}
cluster_labels = np.unique(clusters) # unique labels
n_clusters = cluster_labels.shape[0]
for c in cluster_labels:
size[c] = len(data[clusters == c])
return size
size = cluster_sizes(clusters, X)
for c in size.keys():
print("Size of Cluster", c, "= ", size[c])
Size of Cluster 0 = 1388 Size of Cluster 1 = 9421 Size of Cluster 2 = 5478 Size of Cluster 3 = 1555 Size of Cluster 4 = 2776
np.unique(clusters, return_counts=True)
(array([0, 1, 2, 3, 4], dtype=int32), array([1388, 9421, 5478, 1555, 2776]))
counter = 0
for df in genres_train:
print(f'size of genre {counter}: ', df.shape[0])
counter += 1
size of genre 0: 4221 size of genre 1: 3835 size of genre 2: 4196 size of genre 3: 3708 size of genre 4: 4658
Cluster 2 seems the closest to any real cluster.
Let's see how well it'll predict on our test sample.
Y = test_matrix.drop(columns=['year'])
Y_labels_true = Y.pop('genre')
Y = Y.values
Y_labels_true = Y_labels_true.values
np.unique(clusters, return_counts=True)
(array([0, 1, 2, 3, 4], dtype=int32), array([1388, 9421, 5478, 1555, 2776]))
test_clusters = kmeans.predict(Y)
size = cluster_sizes(test_clusters, Y)
for c in size.keys():
print("Size of Cluster", c, "= ", size[c])
counter = 0
for df in genres_test:
print(f'size of genre {counter}: ', df.shape[0])
counter += 1
Size of Cluster 0 = 172 Size of Cluster 1 = 964 Size of Cluster 2 = 587 Size of Cluster 3 = 147 Size of Cluster 4 = 639 size of genre 0: 518 size of genre 1: 453 size of genre 2: 513 size of genre 3: 450 size of genre 4: 575
# Accuracy Scores
print("Homogeneity: %0.3f" % metrics.homogeneity_score(Y_labels_true, test_clusters))
print("Completeness: %0.3f" % metrics.completeness_score(Y_labels_true, test_clusters))
print("V-measure (Combined Homogeneity & Completeness scores): %0.3f" % metrics.v_measure_score(Y_labels_true, test_clusters))
Homogeneity: 0.102 Completeness: 0.117 V-measure (Combined Homogeneity & Completeness scores): 0.109
Although we were able to give our kMeans algorithm the correct amount of genres (aka clusters) to predict on, we still find ourselves with low accuracy scores. We continue to find evidence leading us to determine one cannot predict a song's popularity nor its genre by the basic features given to us by Spotify.